(SST) ShlWAPI.pas Version 1.08

Developer Reference
(SST)ShlWAPI SHAnsiToUnicode Function
Converts the characters of an ANSI string into Unicode characters and writes them into the provided buffer.
Scope
Global (i.e. this function can be called/accessed from code in any unit that includes/uses (SST)ShlWAPI.pas).
Syntax
function SHAnsiToUnicode(pszSrc : LPCSTR; pwszDst : LPWSTR; cwchBuf : Integer) : Integer;
Parameters
pszSrc [in] The address of, or a pointer to, the zero-terminated, ANSI string to copy and convert.
pwszDst [out] The address of, or a pointer to, the null-terminated buffer, into which the function should write the Unicode conversion of the input string.
cwchBuf [in] Size, in number Unicode characters, of the buffer specified in parameter pwszDst.
Return Values
If the function succeeds, it returns the number of characters (including the terminating DBCS character) it wrote into the the buffer specified in pwszDst. If the function fails for any reason, it returns zero (0).
Remarks
The function always terminates the output string it writes into the provided buffer with a terminating, Unicode (i.e. DBCS) character, even if the buffer is only large enough to accomodata the terminating, double byte character itself.
Even if the function only writes the terminating, Unicode, null-character into the buffer (i.e. the buffer is only large enough to accomodate a single DBCS character) the return value represents the exact number of characters written to the ouput buffer, which in this case it would be 1 (see example output below).
Contrary to the Microsoft documentation accomponying MS SDK 6.1, if the converted output string is truncated, typically because the output buffer is not large enough, this fact and the number of converted or omitted characters, can be easily determined by subtracting the value returned by the function from the length (including the terminating null character) of the ANSI input string. However, this feature can, but should not be used to determine the required output buffer size (see next, two remarks, below).
Unlike many other Windows, API functions, SHAnsiToUnicode does not return the required buffer size if zero (0) is specified in the cwchBuf parameter, nor if an invalid (e.g. NIL) pointer is passed to the function in pwszDst. However, calling the Windows API GetLastError() after having called the function with an inadequate buffer size that is larger than zero (i.e. sizeof(buffer) > 0) typically returns Windows error code 122 (= ERROR_INSUFFICIENT_BUFFER), at least under Windows Vista with SP 1 and IE 8. But, this remains to be tested under other Windows and ShlWAPI.dll versions.
In the documentation accompanying MS SDK 6.1, Microsoft stresses, that calling the function with an insufficiently sized output buffer can compromise application security thru buffer overruns. The function should therefore not be called with an output bffer that cannot store the entire, converted string, including the terminating DBCS null character. Specifying overlapping in- and output buffers (i.e. buffers that share the same memory range) should also be avoided.
The function is exported by name as of ShlWAPI.dll version 6.0 under Vista, but according to the declaration and documentation accompanying MS SDK 6.1, is available as of ShlWAPI.dll 5.0 under Windows 2000. Unfortunately, an ordinal by which function can be accessed in versions pre-dating Vista was not documented. Nonetheless, we were able to determine that the function is exported by ordinal 215 down to, and including at least, Windows NT 4.0 with Internet Explorer 5.0 and 98 SE with Internet Explorer 5.0.
Example
PROCEDURE TForm4.TestShlWAPISHAnsiToUnicode(Sender : TObject); //Support for function as ordinal 215 under Win 98 SE (with IE 5.0) confirmed !!! //Support for function as ordinal 215 under NT 4.0 with IE 5.0 confirmed !!! VAR srcansibuf : STRING; VAR srcstrlen : INTEGER; VAR destwcharbuf : ARRAY[0..64] OF WideChar; VAR destbufsize : INTEGER; VAR apiretval : INTEGER; VAR errorcode : INTEGER; VAR newinfoline : STRING; BEGIN srcansibuf := ''; FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 0; apiretval := 0; errorcode := 0; newinfoline := ''; SetLastError(NO_ERROR); //errorcode := INTEGER(GetLastError()); //uncomment to verify that the last error PRIOR to the function call is 0 srcansibuf := 'Hello Ansi to Unicode World'; srcstrlen := Length(srcansibuf); destbufsize := Length(destwcharbuf); newinfoline := 'SHAnsiToUnicode called with source string "' + srcansibuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; //errorcode := INTEGER(GetLastError()); //uncomment to determine the last error prior to the function call SetLastError(NO_ERROR); apiretval := SHAnsiToUnicode(PChar(srcansibuf), destwcharbuf, destbufsize); //errorcode := INTEGER(GetLastError()); //uncomment to determine the last error after the function call IF apiretval > 0 THEN newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"' ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); //errorcode := INTEGER(GetLastError()); //uncomment to determine the last error after the function call //Dest buffer length parameter set to 23 (too short by 5 character) FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 23; apiretval := 0; newinfoline := ''; errorcode := 0; newinfoline := 'SHAnsiToUnicode called with source string "' + srcansibuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; SetLastError(NO_ERROR); apiretval := SHAnsiToUnicode(PChar(srcansibuf), destwcharbuf, destbufsize); IF apiretval > 0 THEN BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"'; Memo1.Lines.Add(newinfoline); newinfoline := 'and GetLastError returned : ' + IntToStr(errorcode); END ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); //Dest buffer length parameter set to 2 (too short by 26 characters) FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 2; apiretval := 0; newinfoline := ''; errorcode := 0; newinfoline := 'SHAnsiToUnicode called with source string "' + srcansibuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; SetLastError(NO_ERROR); apiretval := SHAnsiToUnicode(PChar(srcansibuf), destwcharbuf, destbufsize); IF apiretval > 0 THEN BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"'; Memo1.Lines.Add(newinfoline); newinfoline := 'and GetLastError returned : ' + IntToStr(errorcode); END ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); //Dest buffer length parameter set to 1 (too short by 27 characters) FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 1; apiretval := 0; newinfoline := ''; errorcode := 0; newinfoline := 'SHAnsiToUnicode called with source string "' + srcansibuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; SetLastError(NO_ERROR); apiretval := SHAnsiToUnicode(PChar(srcansibuf), destwcharbuf, destbufsize); IF apiretval > 0 THEN BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"'; Memo1.Lines.Add(newinfoline); newinfoline := 'and GetLastError returned : ' + IntToStr(errorcode); END ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); //Dest buffer length parameter set to 0 FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 0; apiretval := 0; newinfoline := ''; errorcode := 0; SetLastError(NO_ERROR); newinfoline := 'SHAnsiToUnicode called with source string "' + srcansibuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; apiretval := SHAnsiToUnicode(PChar(srcansibuf), destwcharbuf, destbufsize); IF apiretval > 0 THEN newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"' ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); //No dest buffer (pointer param set to NIL) //and buffer length parameter set to 0 FillChar(destwcharbuf, SizeOf(destwcharbuf), #0); destbufsize := 0; apiretval := 0; newinfoline := ''; errorcode := 0; SetLastError(NO_ERROR); newinfoline := 'SHAnsiToUnicode called with source string "' + srcansibuf + '" (length: ' + IntToStr(srcstrlen) + ') returned : '; apiretval := SHAnsiToUnicode(PChar(srcansibuf), NIL, 0); IF apiretval > 0 THEN newinfoline := newinfoline + IntToStr(apiretval) + ' and in the dest buffer : "' + destwcharbuf + '"' ELSE BEGIN errorcode := INTEGER(GetLastError()); newinfoline := newinfoline + IntToStr(apiretval) + ' (the function call FAILED !), GetLastError returned : ' + IntToStr(errorcode); END; Memo1.Lines.Add(newinfoline); Memo1.Lines.Add(''); END;
When run under Windows Vista with SP 1 and IE 8, the above code produces the following output (note the last error(s) reurned by the Windows API function GetLastError):
SHAnsiToUnicode called with source string "Hello Ansi to Unicode World" (length: 27) returned : 28 and in the dest buffer : "Hello Ansi to Unicode World" SHAnsiToUnicode called with source string "Hello Ansi to Unicode World" (length: 27) returned : 23 and in the dest buffer : "Hello Ansi to Unicode " and GetLastError returned : 122 SHAnsiToUnicode called with source string "Hello Ansi to Unicode World" (length: 27) returned : 2 and in the dest buffer : "H" and GetLastError returned : 122 SHAnsiToUnicode called with source string "Hello Ansi to Unicode World" (length: 27) returned : 1 and in the dest buffer : "" and GetLastError returned : 122 SHAnsiToUnicode called with source string "Hello Ansi to Unicode World" (length: 27) returned : 0 (the function call FAILED !), GetLastError returned : 0 SHAnsiToUnicode called with source string "Hello Ansi to Unicode World" (length: 27) returned : 0 (the function call FAILED !), GetLastError returned : 0
Requirements
Unit: Declared and imported in (SST)ShlWAPI.pas
Library: (SST)ShlWAPI.dcu/(SST)ShlWAPI.obj
Unicode: Not applicable.
Min. ShlWAPI.dll version according to MS SDK doc.: 5.0
Min. ShlWAPI.dll version based on SST research: 5.0
Min. OS version(s) according to Microsoft SDK doc.: Windows 2000, Windows 2000 Server, Windows Server 2003, Windows XP
Min. OS version(s) according to SST research.: Windows NT 4.0 with IE 5, Windows 98 SE with IE 5, Windows 2000, Windows XP, Windows Server 2003.
See Also
SHUnicodeToAnsi, SHAnsiToAnsi, SHUnicodeToUnicode.
 
Windows APIs: SHAnsiToUnicode, SHUnicodeToAnsi, SHUnicodeToUnicode SHAnsiToAnsi.


Document/Contents version 1.00
Page/URI last updated on 07.12.2023
 
Copyright © Stoelzel Software Technologie (SST) 2010 - 2015
Suggestions and comments mail to:
webmaster@stoelzelsoftwaretech.com